package com.fallsvc.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.fallsvc.api.pojo.BlogServiceApi;
import com.fallsvc.api.pojo.response.BlogInfoResponse;
import com.fallsvc.common.exception.BlogException;
import com.fallsvc.common.pojo.Result;
import com.fallsvc.common.utils.*;
import com.fallsvc.user.api.pojo.request.UserInfoRegisterRequest;
import com.fallsvc.user.api.pojo.request.UserInfoRequest;
import com.fallsvc.user.api.pojo.response.UserInfoResponse;
import com.fallsvc.user.api.pojo.response.UserLoginResponse;
import com.fallsvc.user.constant.Constants;
import com.fallsvc.user.convert.BeanConvert;
import com.fallsvc.user.dataobject.UserInfo;
import com.fallsvc.user.mapper.UserInfoMapper;
import com.fallsvc.user.service.UserService;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private BlogServiceApi blogServiceApi;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    private static final Long EXPIRE_TIME = 14*24*60*60L;
    private final String USER_PREFIX = "user";

    @Override
    public UserLoginResponse login(UserInfoRequest user) {
        //验证账号密码是否正确
        UserInfo userInfo = queryUserInfoByName(user.getUserName());
        if (userInfo==null || userInfo.getId()==null){
            throw new BlogException("用户不存在");
        }
//        if (!user.getPassword().equals(userInfo.getPassword())){
//            throw new BlogException("用户密码不正确");
//        }
        if (!SecurityUtil.verify(user.getPassword(),userInfo.getPassword())){
            throw new BlogException("用户密码不正确");
        }
        //账号密码正确的逻辑
        Map<String,Object> claims = new HashMap<>();
        claims.put("id", userInfo.getId());
        claims.put("name", userInfo.getUserName());

        String jwt = JWTUtils.genJwt(claims);
        return new UserLoginResponse(userInfo.getId(), jwt);
    }


    @Override
    public UserInfoResponse getUserInfo(Integer userId) {
        UserInfoResponse userInfoResponse = new UserInfoResponse();
        UserInfo userInfo = selectUserInfoById(userId);
        BeanUtils.copyProperties(userInfo, userInfoResponse);
        return userInfoResponse;
    }

    @Override
    public UserInfoResponse selectAuthorInfoByBlogId(Integer blogId) {
        UserInfoResponse userInfoResponse = new UserInfoResponse();
        //1. 根据博客ID, 获取作者ID
        Result<BlogInfoResponse> blogDeatail = blogServiceApi.getBlogDeatail(blogId);


        //2. 根据作者ID, 获取作者信息
        if (blogDeatail == null || blogDeatail.getData() == null){
            throw new BlogException("博客不存在");
        }
        UserInfo userInfo = selectUserInfoById(blogDeatail.getData().getUserId());
        BeanUtils.copyProperties(userInfo, userInfoResponse);
        return userInfoResponse;
    }

    @Override
    public Integer register(UserInfoRegisterRequest registerRequest) {
        // 参数校验
        checkUserInfo(registerRequest);
        // 用户注册，插入数据库
        UserInfo userInfo = BeanConvert.convertUserInfoByEncrypt(registerRequest);

        try {
            int result = userInfoMapper.insert(userInfo);
            if(result == 1) {
                // 如果异常不进行处理 , redis 储存失败 后面会查询数据库
                redisUtil.set(buildKey(userInfo.getUserName()), JsonUtil.toJson(userInfo),EXPIRE_TIME);


                // 模拟 正常情况要写一个专门发送信息的返回类
                userInfo.setPassword("");
                rabbitTemplate.convertAndSend(Constants.USER_EXCHANGE_NAME,"",  JsonUtil.toJson(userInfo));
                return userInfo.getId();
            }else {
                throw new BlogException("用户注册失败！");
            }
        } catch (Exception e) {
            log.error("用户注册失败！e:", e);
            throw new BlogException("用户注册失败！");
        }

    }

    private String buildKey(String userName) {
        return redisUtil.buildKey(USER_PREFIX,userName);
    }

    private void checkUserInfo(UserInfoRegisterRequest registerRequest) {
        // 用户名不能重复，
        UserInfo userInfo = selectUserInfoByName(registerRequest.getUserName());

        if(null != userInfo) {
            throw new BlogException("用户名已存在！");
        }
        // 邮箱和url格式
        if (!RegexUtil.checkMail(registerRequest.getEmail())) {
            throw new BlogException("邮箱格式不合法！");
        }
        if (!RegexUtil.checkURL(registerRequest.getGithubUrl())) {
            throw new BlogException("GithubUrl格式不合法！");
        }


    }

    private UserInfo queryUserInfoByName(String userName) {
        // 先从redis中查询数据 
        String key = buildKey(userName);
        if(redisUtil.hasKey(key)) {
            String userJson = redisUtil.get(key);
            if(userJson != null) {
                log.info("从redis获取数据!!!userJson:{}",userJson);
                return JsonUtil.parseJson(userJson,UserInfo.class);
            }
        }

        // 如果redis中没有数据 查询数据库

        UserInfo userInfo = selectUserInfoByName(userName);
        log.info("从mysql获取数据!!!userJson:{}",userInfo);

        // 添加缓存
        if(userInfo!=null ){
            redisUtil.set(key,JsonUtil.toJson(userInfo));
        }
        return userInfo;
    }

    public UserInfo selectUserInfoByName(String userName) {
        return userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>()
                .eq(UserInfo::getUserName, userName).eq(UserInfo::getDeleteFlag, 0));
    }
    private UserInfo selectUserInfoById(Integer userId) {
        return userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>()
                .eq(UserInfo::getId, userId).eq(UserInfo::getDeleteFlag, 0));
    }


}
